package jmind.core.spring;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.AbstractGenericHttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Type;

/**
 <bean
 class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
 <property name="webBindingInitializer">
 <bean class="jmind.core.spring.SpringBinder" />
 </property>
 <property name="messageConverters">
 <list>
 <bean
 class="com.yongche.dispatch.FastJsonHttpMessageConverter">
 <property name="supportedMediaTypes">
 <list>
 <value>text/plain;charset=UTF-8</value>
 <value>application/json;charset=UTF-8</value>
 </list>
 </property>
 <property name="fastJsonConfig">
 <bean class="com.alibaba.fastjson.support.config.FastJsonConfig" id="fastJsonConfig">
 <property name="serializerFeatures">
 <array>
 <value>WriteDateUseDateFormat</value>
 <value>DisableCircularReferenceDetect</value>
 <value>WriteEnumUsingName</value>
 <value>PrettyFormat</value>
 </array>
 </property>
 </bean>
 </property>
 </bean>

 </list>
 </property>
 </bean>

 * http://www.tuicool.com/articles/vUJBFn
 * @author xieweibo
 * @date 2015年3月9日
 */




/**
 * Fastjson for Spring MVC Converter.
 * <p>
 * Compatible Spring MVC version 4.2+
 *
 * @author Victor.Zxy
 * @see AbstractGenericHttpMessageConverter
 * @since 1.2.11
 */
public class FastJsonHttpMessageConverter //
        extends AbstractGenericHttpMessageConverter<Object> {

    /**
     * with fastJson config
     */
    private FastJsonConfig fastJsonConfig = new FastJsonConfig();

    /**
     * @return the fastJsonConfig.
     * @since 1.2.11
     */
    public FastJsonConfig getFastJsonConfig() {
        return fastJsonConfig;
    }

    /**
     * @param fastJsonConfig the fastJsonConfig to set.
     * @since 1.2.11
     */
    public void setFastJsonConfig(FastJsonConfig fastJsonConfig) {
        this.fastJsonConfig = fastJsonConfig;
    }

    /**
     * Can serialize/deserialize all types.
     */
    public FastJsonHttpMessageConverter() {

        super(MediaType.ALL);
    }

    @Override
    protected boolean supports(Class<?> paramClass) {
        return true;
    }

    public boolean canRead(Class<?> clazz, MediaType mediaType) {
        return true;
    }

    @Override
    public boolean canWrite(Class<?> clazz, MediaType mediaType) {
        return true;
    }

    /**
     *
     * 对应 @RequestBody参数使用
     * curl -X POST -d '{name:"wave",pwd:"acd"}' -H "Content-Type:application/json" http://localhost:8081/lady
     */
    @Override
    public Object read(Type type, //
                       Class<?> contextClass, //
                       HttpInputMessage inputMessage //
    ) throws IOException, HttpMessageNotReadableException {
        InputStream in = inputMessage.getBody();
        return JSON.parseObject(in, fastJsonConfig.getCharset(), type, fastJsonConfig.getFeatures());
    }

    @Override
    protected void writeInternal(Object obj, //
                                 Type type, //
                                 HttpOutputMessage outputMessage //
    ) throws IOException, HttpMessageNotWritableException {
        if(obj==null)
            return ;
        HttpHeaders headers = outputMessage.getHeaders();
        if(type.equals(String.class)){
            String s= (String) obj;
            headers.setContentLength(s.length());
            OutputStream out = outputMessage.getBody();
            out.write(s.getBytes(fastJsonConfig.getCharset()));
            out.flush();
        }else{
            ByteArrayOutputStream outnew = new ByteArrayOutputStream();
            int len = JSON.writeJSONString(outnew, //
                    fastJsonConfig.getCharset(), //
                    obj, //
                    fastJsonConfig.getSerializeConfig(), //
                    fastJsonConfig.getSerializeFilters(), //
                    fastJsonConfig.getDateFormat(), //
                    JSON.DEFAULT_GENERATE_FEATURE, //
                    fastJsonConfig.getSerializerFeatures());
            headers.setContentLength(len);
            OutputStream out = outputMessage.getBody();
            outnew.writeTo(out);
            outnew.close();
        }

    }

    @Override
    protected Object readInternal(Class<? extends Object> clazz, //
                                  HttpInputMessage inputMessage //
    ) throws IOException, HttpMessageNotReadableException {

        InputStream in = inputMessage.getBody();
        return JSON.parseObject(in, fastJsonConfig.getCharset(), clazz, fastJsonConfig.getFeatures());
    }
}
